home *** CD-ROM | disk | FTP | other *** search
- Subject: v21i086: File distribution alternative to rdist, Part03/03
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 72edbc40 a1f4390d a164fdd4 1e4b62b8
-
- Submitted-by: Rich Salz <rsalz@bbn.com>
- Posting-number: Volume 21, Issue 86
- Archive-name: coda/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 3)."
- # Contents: COPYING client.c coda.1
- # Wrapped by rsalz@litchi.bbn.com on Mon Apr 9 16:49:04 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'COPYING' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'COPYING'\"
- else
- echo shar: Extracting \"'COPYING'\" \(9934 characters\)
- sed "s/^X//" >'COPYING' <<'END_OF_FILE'
- X GNU GENERAL PUBLIC LICENSE
- X Version 1, February 1989
- X
- X Copyright (C) 1989 Free Software Foundation, Inc.
- X 675 Mass Ave, Cambridge, MA 02139, USA
- X Everyone is permitted to copy and distribute verbatim copies
- X of this license document, but changing it is not allowed.
- X
- X Preamble
- X
- X The license agreements of most software companies try to keep users
- Xat the mercy of those companies. By contrast, our General Public
- XLicense is intended to guarantee your freedom to share and change free
- Xsoftware--to make sure the software is free for all its users. The
- XGeneral Public License applies to the Free Software Foundation's
- Xsoftware and to any other program whose authors commit to using it.
- XYou can use it for your programs, too.
- X
- X When we speak of free software, we are referring to freedom, not
- Xprice. Specifically, the General Public License is designed to make
- Xsure that you have the freedom to give away or sell copies of free
- Xsoftware, that you receive source code or can get it if you want it,
- Xthat you can change the software or use pieces of it in new free
- Xprograms; and that you know you can do these things.
- X
- X To protect your rights, we need to make restrictions that forbid
- Xanyone to deny you these rights or to ask you to surrender the rights.
- XThese restrictions translate to certain responsibilities for you if you
- Xdistribute copies of the software, or if you modify it.
- X
- X For example, if you distribute copies of a such a program, whether
- Xgratis or for a fee, you must give the recipients all the rights that
- Xyou have. You must make sure that they, too, receive or can get the
- Xsource code. And you must tell them their rights.
- X
- X We protect your rights with two steps: (1) copyright the software, and
- X(2) offer you this license which gives you legal permission to copy,
- Xdistribute and/or modify the software.
- X
- X Also, for each author's protection and ours, we want to make certain
- Xthat everyone understands that there is no warranty for this free
- Xsoftware. If the software is modified by someone else and passed on, we
- Xwant its recipients to know that what they have is not the original, so
- Xthat any problems introduced by others will not reflect on the original
- Xauthors' reputations.
- X
- X The precise terms and conditions for copying, distribution and
- Xmodification follow.
- X
- X GNU GENERAL PUBLIC LICENSE
- X TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- X
- X 0. This License Agreement applies to any program or other work which
- Xcontains a notice placed by the copyright holder saying it may be
- Xdistributed under the terms of this General Public License. The
- X"Program", below, refers to any such program or work, and a "work based
- Xon the Program" means either the Program or any work containing the
- XProgram or a portion of it, either verbatim or with modifications. Each
- Xlicensee is addressed as "you".
- X
- X 1. You may copy and distribute verbatim copies of the Program's source
- Xcode as you receive it, in any medium, provided that you conspicuously and
- Xappropriately publish on each copy an appropriate copyright notice and
- Xdisclaimer of warranty; keep intact all the notices that refer to this
- XGeneral Public License and to the absence of any warranty; and give any
- Xother recipients of the Program a copy of this General Public License
- Xalong with the Program. You may charge a fee for the physical act of
- Xtransferring a copy.
- X
- X 2. You may modify your copy or copies of the Program or any portion of
- Xit, and copy and distribute such modifications under the terms of Paragraph
- X1 above, provided that you also do the following:
- X
- X a) cause the modified files to carry prominent notices stating that
- X you changed the files and the date of any change; and
- X
- X b) cause the whole of any work that you distribute or publish, that
- X in whole or in part contains the Program or any part thereof, either
- X with or without modifications, to be licensed at no charge to all
- X third parties under the terms of this General Public License (except
- X that you may choose to grant warranty protection to some or all
- X third parties, at your option).
- X
- X c) If the modified program normally reads commands interactively when
- X run, you must cause it, when started running for such interactive use
- X in the simplest and most usual way, to print or display an
- X announcement including an appropriate copyright notice and a notice
- X that there is no warranty (or else, saying that you provide a
- X warranty) and that users may redistribute the program under these
- X conditions, and telling the user how to view a copy of this General
- X Public License.
- X
- X d) You may charge a fee for the physical act of transferring a
- X copy, and you may at your option offer warranty protection in
- X exchange for a fee.
- X
- XMere aggregation of another independent work with the Program (or its
- Xderivative) on a volume of a storage or distribution medium does not bring
- Xthe other work under the scope of these terms.
- X
- X 3. You may copy and distribute the Program (or a portion or derivative of
- Xit, under Paragraph 2) in object code or executable form under the terms of
- XParagraphs 1 and 2 above provided that you also do one of the following:
- X
- X a) accompany it with the complete corresponding machine-readable
- X source code, which must be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X b) accompany it with a written offer, valid for at least three
- X years, to give any third party free (except for a nominal charge
- X for the cost of distribution) a complete machine-readable copy of the
- X corresponding source code, to be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X c) accompany it with the information you received as to where the
- X corresponding source code may be obtained. (This alternative is
- X allowed only for noncommercial distribution and only if you
- X received the program in object code or executable form alone.)
- X
- XSource code for a work means the preferred form of the work for making
- Xmodifications to it. For an executable file, complete source code means
- Xall the source code for all modules it contains; but, as a special
- Xexception, it need not include source code for modules which are standard
- Xlibraries that accompany the operating system on which the executable
- Xfile runs, or for standard header files or definitions files that
- Xaccompany that operating system.
- X
- X 4. You may not copy, modify, sublicense, distribute or transfer the
- XProgram except as expressly provided under this General Public License.
- XAny attempt otherwise to copy, modify, sublicense, distribute or transfer
- Xthe Program is void, and will automatically terminate your rights to use
- Xthe Program under this License. However, parties who have received
- Xcopies, or rights to use copies, from you under this General Public
- XLicense will not have their licenses terminated so long as such parties
- Xremain in full compliance.
- X
- X 5. By copying, distributing or modifying the Program (or any work based
- Xon the Program) you indicate your acceptance of this license to do so,
- Xand all its terms and conditions.
- X
- X 6. Each time you redistribute the Program (or any work based on the
- XProgram), the recipient automatically receives a license from the original
- Xlicensor to copy, distribute or modify the Program subject to these
- Xterms and conditions. You may not impose any further restrictions on the
- Xrecipients' exercise of the rights granted herein.
- X
- X 7. The Free Software Foundation may publish revised and/or new versions
- Xof the General Public License from time to time. Such new versions will
- Xbe similar in spirit to the present version, but may differ in detail to
- Xaddress new problems or concerns.
- X
- XEach version is given a distinguishing version number. If the Program
- Xspecifies a version number of the license which applies to it and "any
- Xlater version", you have the option of following the terms and conditions
- Xeither of that version or of any later version published by the Free
- XSoftware Foundation. If the Program does not specify a version number of
- Xthe license, you may choose any version ever published by the Free Software
- XFoundation.
- X
- X 8. If you wish to incorporate parts of the Program into other free
- Xprograms whose distribution conditions are different, write to the author
- Xto ask for permission. For software which is copyrighted by the Free
- XSoftware Foundation, write to the Free Software Foundation; we sometimes
- Xmake exceptions for this. Our decision will be guided by the two goals
- Xof preserving the free status of all derivatives of our free software and
- Xof promoting the sharing and reuse of software generally.
- X
- X NO WARRANTY
- X
- X 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
- XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
- XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
- XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
- XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
- XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
- XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
- XREPAIR OR CORRECTION.
- X
- X 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
- XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
- XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
- XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
- XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
- XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
- XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
- XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
- XPOSSIBILITY OF SUCH DAMAGES.
- X
- X END OF TERMS AND CONDITIONS
- END_OF_FILE
- if test 9934 -ne `wc -c <'COPYING'`; then
- echo shar: \"'COPYING'\" unpacked with wrong size!
- fi
- # end of 'COPYING'
- fi
- if test -f 'client.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'client.c'\"
- else
- echo shar: Extracting \"'client.c'\" \(15213 characters\)
- sed "s/^X//" >'client.c' <<'END_OF_FILE'
- X/*
- X** Copyright 1989 BBN Systems and Technologies Corporation.
- X** All Rights Reserved.
- X** This is free software, and may be distributed under the terms of the
- X** GNU Public License; see the file COPYING for more details.
- X**
- X** Main code for CODA client.
- X*/
- X#define MAINLINE
- X#include "client.h"
- X#ifndef VMS
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#else
- X#include <types.h>
- X#include <stat.h>
- X#endif /* VMS */
- X#ifdef RCSID
- Xstatic char RCS[] =
- X "$Header: client.c,v 2.0 90/04/09 15:34:23 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X/*
- X** A whole mess of global variables.
- X*/
- XSTATIC char ACK[] = "ACK-"; /* Header if command was OK */
- XSTATIC char DAT[] = "DAT ITEM "; /* Data file for from command */
- XSTATIC char NAK[] = "NAK-"; /* Header if it wasn't */
- XSTATIC char **Lines; /* Lines read from server */
- XSTATIC char *Directory; /* Where sources reside */
- XSTATIC char *Filename; /* File for server to read */
- XSTATIC char *Root; /* Remote root directory */
- XSTATIC char *ServerHost; /* Host server is on */
- XSTATIC char *UserName; /* Remote user name */
- XSTATIC char *UserPass; /* Remote user password */
- XSTATIC int MaxLines; /* Number of lines allocated */
- XSTATIC BOOL Noaction; /* Just say what's outdated? */
- XSTATIC int NumLines; /* Number of lines used */
- XSTATIC int Port = PORTNUMBER; /* Port server is listening */
- XSTATIC int Verbose; /* Tell what we're doing? */
- XSTATIC BOOL ChangeOwner; /* Try to give away files? */
- XSTATIC BOOL SlowMode; /* Do byte comparisons? */
- XSTATIC BOOL YoungerMode; /* Can client have newer files? */
- X
- X
- X
- X/*
- X** Print an error message and exit.
- X*/
- Xvoid
- XFatal(p)
- X char *p;
- X{
- X (void)fprintf(stderr, "Coda fatal error:\n\t%s\n", p);
- X exit(EXITERR);
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X** Get a line from the server; if it's a NAK, quit.
- X*/
- XSTATIC void
- XQuitOnNack()
- X{
- X char buff[SIZE];
- X
- X if (!SRVget(buff, sizeof buff))
- X Fatal("Server did not reply");
- X if (strncmp(buff, ACK, sizeof ACK - 1) == 0)
- X return;
- X if (strncmp(buff, NAK, sizeof NAK - 1) == 0)
- X Fatal(&buff[sizeof NAK - 1]);
- X (void)fprintf(stderr, "Bad from server:\n\t%s\n", buff);
- X Fatal("Protocol error");
- X}
- X
- X
- X/*
- X** Print a warning if user wants to see them.
- X*/
- XSTATIC void
- XCant(Always, Action, Name)
- X BOOL Always;
- X char *Action;
- X char *Name;
- X{
- X char buff[SIZE];
- X int e;
- X
- X if (Always || Verbose > 2) {
- X e = errno;
- X (void)sprintf(buff, "Can't %s %s", Action, Name);
- X errno = e;
- X perror(buff);
- X }
- X}
- X
- X
- X
- X/*
- X** Set the mode, ownership, etc., on an item to be what they should be.
- X*/
- XSTATIC void
- XSetStuff(Name, Mode, Uid, Gid, Time)
- X char *Name;
- X int Mode;
- X int Uid;
- X int Gid;
- X long Time;
- X{
- X struct stat Sb;
- X#ifdef ATTsysv
- X struct utime_t {
- X time_t x;
- X time_t y;
- X } t, *vec = &t;
- X#else
- X time_t vec[2];
- X#endif /* ATTsysv */
- X
- X /* Get current status. */
- X if (stat(Name, &Sb) < 0) {
- X Cant(TRUE, "stat", Name);
- X return;
- X }
- X
- X /* Fix up the permissions on files. */
- X if ((Sb.st_mode & 0777) != Mode) {
- X if (chmod(Name, Mode) < 0)
- X Cant(FALSE, "chmod", Name);
- X else if (Verbose > 1)
- X (void)printf("chmod 0%o %s\n", Mode, Name);
- X }
- X
- X /* Fix up the modication time. */
- X if (Sb.st_mtime != Time) {
- X#ifdef ATTsysv
- X t.x = t.y = Time;
- X#else
- X vec[0] = vec[1] = Time;
- X#endif /* ATTsysv */
- X if (utime(Name, vec) < 0)
- X Cant(FALSE, "set time", Name);
- X else if (Verbose > 1)
- X (void)printf("settime %ld %s\n", (long)Time, Name);
- X }
- X
- X /* Fix up the owner. */
- X if (ChangeOwner && (Sb.st_uid != Uid || Sb.st_gid != Gid)) {
- X if (chown(Name, Uid, Gid) < 0)
- X Cant(FALSE, "chown", Name);
- X else if (Verbose > 1)
- X (void)printf("chown %d chgrp %d %s\n", Uid, Gid, Name);
- X }
- X}
- X
- X
- X/*
- X** Do what's necessary to create a directory.
- X*/
- XSTATIC void
- XDoDir(Name, Uid, Gid, Mode, Time)
- X char *Name;
- X int Uid;
- X int Gid;
- X int Mode;
- X long Time;
- X{
- X struct stat Sb;
- X#ifdef VMS
- X char buff[SIZE];
- X#endif /* VMS */
- X
- X#ifdef VMS
- X (void)sprintf(buff, "%s.dir", Name);
- X Name = buff;
- X#endif /* VMS */
- X
- X /* If directory doesn't exist, create it. */
- X if (stat(Name, &Sb) < 0) {
- X if (Verbose > 0 || Noaction) {
- X (void)printf("mkdir %s\n", Name);
- X if (Noaction)
- X return;
- X }
- X if (mkdir(Name, Mode) < 0)
- X Cant(TRUE, "mkdir", Name);
- X }
- X
- X /* Set the other bits. */
- X if (!Noaction)
- X SetStuff(Name, Mode, Uid, Gid, Time);
- X}
- X
- X
- X
- X/*
- X** Compare two files, if they're different, move the second onto
- X** the first.
- X*/
- XSTATIC void
- XGetFile(Name, Size, KnowItsWrong)
- X char *Name;
- X REGISTER long Size;
- X BOOL KnowItsWrong;
- X{
- X REGISTER FILE *F;
- X REGISTER FILE *Old;
- X REGISTER char *p;
- X REGISTER int c;
- X REGISTER int c2;
- X char buff[SIZE];
- X char temp[SIZE];
- X
- X if (!KnowItsWrong && Verbose > 4)
- X (void)printf("Checking %s\n", Name);
- X
- X /* Make a temporary filename in the same directory. */
- X (void)strcpy(temp, Name);
- X if (p = strrchr(temp, '/'))
- X p++;
- X else
- X p = temp;
- X (void)strcpy(p, "codaXXXXXX");
- X (void)mktemp(p);
- X
- X if ((F = fopen(temp, "w")) == NULL) {
- X Cant(TRUE, "fopen", temp);
- X return;
- X }
- X
- X /* Tell the server to send us the file. */
- X (void)sprintf(buff, "SEND %s\n", Name);
- X SRVput(buff);
- X if (!SRVget(buff, sizeof buff)
- X || strncmp(buff, NAK, sizeof NAK - 1) == 0) {
- X Cant(TRUE, "start to read", temp);
- X (void)fclose(F);
- X (void)unlink(temp);
- X return;
- X }
- X
- X /* Read it from the server. */
- X while (--Size >= 0) {
- X c = SRVcget();
- X (void)putc(c, F);
- X }
- X (void)fclose(F);
- X QuitOnNack();
- X
- X /* If we know it's wrong, just move it. */
- X if (KnowItsWrong) {
- X (void)unlink(Name);
- X if (rename(temp, Name) < 0)
- X Cant(TRUE, "rename to", Name);
- X (void)sprintf(buff, "MESG took %s\n", Name);
- X SRVput(buff);
- X QuitOnNack();
- X return;
- X }
- X
- X /* Open both old and new files. */
- X if ((F = fopen(temp, "r")) == NULL) {
- X Cant(TRUE, "reopen", temp);
- X return;
- X }
- X if ((Old = fopen(Name, "r")) == NULL) {
- X Cant(TRUE, "fopen", Name);
- X (void)fclose(F);
- X return;
- X }
- X
- X /* Do byte-for-byte comparisons. */
- X while ((c = getc(F)) == (c2 = getc(Old)))
- X if (c == EOF)
- X break;
- X (void)fclose(F);
- X (void)fclose(Old);
- X
- X /* Different? */
- X if (c != c2) {
- X if (Verbose || Noaction) {
- X (void)printf("Update %s\n", Name);
- X if (Noaction) {
- X (void)unlink(temp);
- X return;
- X }
- X }
- X (void)unlink(Name);
- X if (rename(temp, Name) < 0)
- X Cant(TRUE, "rename to", Name);
- X (void)sprintf(buff, "MESG took %s\n", Name);
- X }
- X else
- X (void)sprintf(buff, "MESG ignore %s\n", Name);
- X SRVput(buff);
- X QuitOnNack();
- X (void)unlink(temp);
- X}
- X
- X
- X/*
- X** Do what's necessary to create a file.
- X*/
- XSTATIC void
- XDoFile(Name, Uid, Gid, Mode, Time, Size)
- X char *Name;
- X int Uid;
- X int Gid;
- X int Mode;
- X long Time;
- X long Size;
- X{
- X struct stat Sb;
- X
- X if (stat(Name, &Sb) < 0 || Sb.st_size != Size) {
- X /* File doesn't exist or size is wrong; get it. */
- X if (YoungerMode && Sb.st_mtime > Time) {
- X (void)printf("Younger %s\n", Name);
- X return;
- X }
- X if (Verbose || Noaction) {
- X (void)printf("Update %s\n", Name);
- X if (Noaction)
- X return;
- X }
- X GetFile(Name, Size, TRUE);
- X }
- X else {
- X if (YoungerMode && Sb.st_mtime > Time) {
- X (void)printf("Younger %s\n", Name);
- X return;
- X }
- X if (SlowMode || Sb.st_mtime != Time)
- X /* Slow mode or the times are different; get and check. */
- X GetFile(Name, Size, FALSE);
- X }
- X
- X /* Set the other bits. */
- X if (!Noaction)
- X SetStuff(Name, Mode, Uid, Gid, Time);
- X}
- X
- X
- X/*
- X** Read the list of files from the server, than parse them.
- X*/
- XSTATIC void
- XParseListResult()
- X{
- X REGISTER char **L;
- X REGISTER char **Lend;
- X REGISTER char *p;
- X char buff[SIZE];
- X char *Name;
- X int Uid;
- X int Gid;
- X long Size;
- X long Time;
- X int Mode;
- X int What;
- X
- X /* Read lines from server. */
- X for (NumLines = 0; SRVget(buff, sizeof buff); ) {
- X /* Check for end of list or a bad line. */
- X if (strncmp(buff, NAK, sizeof NAK - 1) == 0) {
- X (void)printf("%s\n", &buff[sizeof NAK - 1]);
- X return;
- X }
- X if (strncmp(buff, ACK, sizeof ACK - 1) == 0) {
- X (void)printf("%s\n", &buff[sizeof ACK - 1]);
- X break;
- X }
- X if (strncmp(buff, DAT, sizeof DAT - 1)) {
- X (void)fprintf(stderr, "Bogus line from the server:\n\t%s\n", buff);
- X continue;
- X }
- X
- X /* Need more room for this line? */
- X if (NumLines == MaxLines - 1) {
- X MaxLines += LINES_DELTA;
- X Lines = GROW(Lines, char*, MaxLines);
- X }
- X Lines[NumLines++] = COPY(&buff[sizeof DAT - 1]);
- X }
- X
- X /* Now loop over what we got and parse it. */
- X for (L = Lines, Lend = &Lines[NumLines]; L < Lend; L++) {
- X /* Set defaults to show the stuff is bad. */
- X Name = NULL;
- X Uid = -1;
- X Gid = -1;
- X Size = -1;
- X Time = -1;
- X Mode = -1;
- X What = -1;
- X for (p = strcpy(buff, *L); *p; ) {
- X switch (*p) {
- X default:
- X (void)fprintf(stderr, "Bad field from server:\n\t%s\n", *L);
- X break;
- X case 'N':
- X Name = &p[2];
- X break;
- X case 'W':
- X if (p[2] == 'd' || p[2] == 'f')
- X What = p[2];
- X break;
- X case 'U':
- X Uid = atoi(&p[2]);
- X break;
- X case 'G':
- X Gid = atoi(&p[2]);
- X break;
- X case 'M':
- X Mode = atoi(&p[2]);
- X break;
- X case 'S':
- X Size = atol(&p[2]);
- X break;
- X case 'T':
- X Time = atol(&p[2]);
- X break;
- X }
- X
- X /* Move to next field. */
- X while (*p && !WHITE(*p))
- X p++;
- X if (*p)
- X for (*p++ = '\0'; *p && WHITE(*p); )
- X p++;
- X }
- X
- X /* Got everything? */
- X if (What < 0 || Mode < 0 || Gid < 0 || Size < 0 || Time < 0
- X#ifdef NOBODY
- X || (Uid < 0 && Uid != NOBODY)
- X#else
- X || Uid < 0
- X#endif /* NOBODY */
- X || Name == NULL)
- X (void)fprintf(stderr, "Badly formed line:\n\t%s\n", *L);
- X else if (What == 'd')
- X DoDir(Name, Uid, Gid, Mode, Time);
- X else
- X DoFile(Name, Uid, Gid, Mode, Time, Size);
- X }
- X}
- X
- X
- X
- X/*
- X** Scan a word for yes or no.
- X*/
- XSTATIC int
- XGetYesOrNo(p, where, flag)
- X char *p;
- X char *where;
- X char flag;
- X{
- X char buff[SIZE];
- X
- X switch (*p++) {
- X case 'Y': case 'y':
- X if (p[0] == '\0')
- X return TRUE;
- X if ((p[1] == 'E' || p[1] == 'e')
- X && (p[2] == 'S' || p[2] == 's')
- X && p[3] == '\0')
- X break;
- X case 'N': case 'n':
- X if (p[0] == '\0')
- X return TRUE;
- X if ((p[1] == 'O' || p[1] == 'o')
- X && p[2] == '\0')
- X return TRUE;
- X break;
- X }
- X (void)sprintf(buff, "Expecting one of [YyNn] %s for '%c' flag", where, flag);
- X Fatal(buff);
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X** Skip past the current word and any whitespace that follows it.
- X*/
- XSTATIC char *
- XSkip(p)
- X char *p;
- X{
- X while (*p && !WHITE(*p))
- X p++;
- X while (*p && WHITE(*p))
- X p++;
- X return p;
- X}
- X
- X
- X/*
- X** Read the init file.
- X*/
- XSTATIC void
- XReadInitFile()
- X{
- X static char Where[] = "in init file";
- X FILE *F;
- X char *p;
- X char buff[SIZE];
- X
- X /* Get the filename, open the file. */
- X if ((p = getenv("CODA")) == NULL || (F = fopen(p, "r")) == NULL) {
- X#ifdef VMS
- X if ((F = fopen(CODA_INIT, "r")) == NULL)
- X return;
- X#else
- X if ((p = getenv("HOME")) == NULL)
- X return;
- X (void)sprintf(buff, CODA_INIT, p);
- X if ((F = fopen(buff, "r")) == NULL)
- X return;
- X#endif /* VMS */
- X }
- X
- X while (fgets(buff, sizeof buff, F)) {
- X /* Skip blank and comment lines. */
- X if (p = strchr(buff, '\n'))
- X *p = '\0';
- X if (buff[0] == '\0' || buff[0] == '#')
- X continue;
- X
- X if (strncmp(buff, "dir", 3) == 0) {
- X p = Skip(buff);
- X Directory = COPY(p);
- X }
- X else if (strncmp(buff, "file", 4) == 0) {
- X p = Skip(buff);
- X Filename = COPY(p);
- X }
- X else if (strncmp(buff, "host", 4) == 0) {
- X p = Skip(buff);
- X ServerHost = COPY(p);
- X }
- X else if (strncmp(buff, "owner", 5) == 0) {
- X p = Skip(buff);
- X ChangeOwner = GetYesOrNo(p, Where, 'o');
- X }
- X else if (strncmp(buff, "pass", 4) == 0) {
- X p = Skip(buff);
- X UserPass = COPY(p);
- X }
- X else if (strncmp(buff, "port", 4) == 0) {
- X p = Skip(buff);
- X Port = atoi(p);
- X }
- X else if (strncmp(buff, "root", 4) == 0) {
- X p = Skip(buff);
- X Root = COPY(p);
- X }
- X else if (strncmp(buff, "slow", 4) == 0) {
- X p = Skip(buff);
- X SlowMode = GetYesOrNo(p, Where, 's');
- X }
- X else if (strncmp(buff, "user", 4) == 0) {
- X p = Skip(buff);
- X UserName = COPY(p);
- X }
- X else if (strncmp(buff, "verb", 4) == 0) {
- X p = Skip(buff);
- X Verbose = atoi(p);
- X }
- X else if (strncmp(buff, "young", 5) == 0) {
- X p = Skip(buff);
- X YoungerMode = GetYesOrNo(p, Where, 'y');
- X }
- X else {
- X (void)fprintf(stderr, "Unknown line:\n\t%s\n", buff);
- X Fatal("Bad init file");
- X }
- X }
- X (void)fclose(F);
- X}
- X
- X
- Xmain(ac, av)
- X int ac;
- X char *av[];
- X{
- X static char Where[] = "on command line";
- X char buff[SIZE];
- X char pass[SIZE];
- X int i;
- X
- X /* Get defaults from environment if possible. */
- X ReadInitFile();
- X (void)umask(0);
- X
- X /* Parse JCL. */
- X while ((i = getopt(ac, av, "cd:f:h:no:p:r:s:tu:v:x:y:")) != EOF)
- X switch (i) {
- X default:
- X Fatal("Bad calling sequence");
- X /* NOTREACHED */
- X case 'c':
- X Copyright();
- X exit(EXITOK);
- X /* NOTREACHED */
- X case 'd':
- X Directory = optarg;
- X break;
- X case 'f':
- X Filename = optarg;
- X break;
- X case 'h':
- X ServerHost = optarg;
- X break;
- X case 'n':
- X Noaction = TRUE;
- X break;
- X case 'o':
- X ChangeOwner = GetYesOrNo(optarg, Where, 'o');
- X break;
- X case 'p':
- X Port = atoi(optarg);
- X break;
- X case 'r':
- X Root = optarg;
- X break;
- X case 's':
- X SlowMode = GetYesOrNo(optarg, Where, 's');
- X break;
- X case 't':
- X SRVtrace = TRUE;
- X break;
- X case 'u':
- X UserName = optarg;
- X break;
- X case 'v':
- X Verbose = atoi(optarg);
- X break;
- X case 'x':
- X UserPass = optarg;
- X break;
- X case 'y':
- X YoungerMode = GetYesOrNo(optarg, Where, 'y');
- X break;
- X }
- X av += optind;
- X
- X /* Got everything we need? */
- X if (ServerHost == NULL)
- X Fatal("Need name of server host");
- X if (Port == 0)
- X Fatal("Need port to connect to");
- X if (UserName == NULL)
- X Fatal("Need your name on the server machine");
- X
- X /* Get passwword. */
- X if (UserPass == NULL) {
- X (void)printf("Enter password:");
- X (void)fflush(stdout);
- X GetPassword(pass, sizeof pass);
- X UserPass = pass;
- X }
- X
- X /* Talk to the server */
- X if (!SRVopen(ServerHost, Port))
- X Fatal("Can't open connection to server");
- X QuitOnNack();
- X
- X /* Log in. */
- X (void)sprintf(buff, "USER %s %s", UserName, UserPass);
- X SRVput(buff);
- X QuitOnNack();
- X
- X /* Tell the server where to go. */
- X if (Directory) {
- X (void)sprintf(buff, "GOTO %s", Directory);
- X SRVput(buff);
- X QuitOnNack();
- X }
- X
- X /* Read the file. */
- X if (Filename) {
- X (void)sprintf(buff, "READ %s", Filename);
- X SRVput(buff);
- X }
- X else
- X SRVput("READ");
- X QuitOnNack();
- X
- X /* Set the root directory. */
- X if (Root) {
- X (void)sprintf(buff, "ROOT %s", Root);
- X SRVput(buff);
- X QuitOnNack();
- X }
- X
- X /* Any other arguments are block names. */
- X if (*av) {
- X /* Get some space. */
- X MaxLines = LINES_DELTA;
- X Lines = NEW(char*, MaxLines);
- X for ( ; *av; av++) {
- X (void)printf("Doing %s...\n", *av);
- X (void)sprintf(buff, "LIST %s", *av);
- X SRVput(buff);
- X ParseListResult();
- X }
- X }
- X else {
- X /* No arguments means do the whole shebang. */
- X MaxLines = LINES_DELTA * 2;
- X Lines = NEW(char*, MaxLines);
- X (void)printf("Working...\n");
- X SRVput("LIST");
- X ParseListResult();
- X }
- X
- X /* That's all she wrote. */
- X SRVclose();
- X exit(EXITOK);
- X /* NOTREACHED */
- X}
- END_OF_FILE
- if test 15213 -ne `wc -c <'client.c'`; then
- echo shar: \"'client.c'\" unpacked with wrong size!
- fi
- # end of 'client.c'
- fi
- if test -f 'coda.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'coda.1'\"
- else
- echo shar: Extracting \"'coda.1'\" \(14762 characters\)
- sed "s/^X//" >'coda.1' <<'END_OF_FILE'
- X.TH CODA 1 LOCAL
- X.SH NAME
- Xcoda \- Code distribution aid
- X.SH SYNOPSIS
- X.RS
- X.ti -.5i
- X.B coda
- X.na
- X[
- X.B \-c
- X] [
- X.BI \-d dir
- X] [
- X.BI \-r dir
- X] [
- X.BI \-h host
- X] [
- X.BI \-p port#
- X] [
- X.BI \-f file
- X] [
- X.BI \-u name
- X] [
- X.BI \-x pass
- X] [
- X.BI \-s y_or_n
- X] [
- X.BI \-y y_or_n
- X] [
- X.BI \-o y_or_n
- X] [
- X.B \-n
- X] [
- X.B \-t
- X] [
- X.B \-v #
- X] [
- X.I names...
- X]
- X.ad
- X.RE
- X.SH DESCRIPTION
- X.I Coda
- Xis used to keep source distributions current across a set of machines.
- XIt is not as flexible as
- X.IR rdist (1),
- Xbut it requires less of the client machines because they do not have to be
- Xrunning Unix or the Berkeley networking programs.
- XThe other difference is that when using
- X.IR rdist ,
- Xthe server ``pushes'' files out to the clients, while with
- X.I coda
- Xthe clients ``pull'' files from the server as they need them.
- X.I Coda
- Xwas designed to have a simple client that easily ports to a wide
- Xvariety of systems.
- X.PP
- XThe most common way of using
- X.I coda
- Xis to create a configuration file in your home directory.
- XOn
- X.SM UNIX
- Xsystems, the file is named
- X.I $HOME/.codarc
- Xwhile on
- X.SM VMS
- Xmachines it is named
- X.IR SYS$LOGIN:CODA.DAT .
- XOn either system, to use a different file, set the environment variable
- X.I CODA
- Xto the name of the file.
- XThis is useful to share a common a file among project members.
- XThe config file identifies where the server host is, your name
- X(and password) on the server, and where the Codafile and sources
- Xare to be found.
- X.PP
- XThe config file is a set of lines that make name-value pairs.
- XLines starting with a pound sign are ignored.
- XThe following is a sample configuration file; the field names are
- Xexplained below:
- X.RS
- X.nf
- X.ta \w'#verbose 'u
- X## Server host and port number
- Xhost papaya.bbn.com
- Xport 1999
- X## Our name and password on the server host
- Xuser rsalz
- Xpass doubtful
- X## Directory to start from, name of the file to read
- Xdir /usr/cronus
- Xfile src/make_all/Codafile
- X##
- X#root /nfs/papaya/u1/cronusbuild/cronus
- Xslow n
- Xverbose 1
- X## Can client have newer files? Yes, while porting to it
- Xyounger y
- X.fi
- X.RE
- X.PP
- XIn addition to using the config file, it is possible to specify the
- Xparameters by using command line flags.
- XAny values set by flags override the values in the config file.
- XThe following tables matches names in the config file to command line flags.
- X.RS
- X.nf
- X.ta \w'younger 'u +\w'Flag 'u
- XFile Flag Meaning
- X\l'5i'
- Xhost \-h Name of the server host
- Xport \-p Port to connect to; default is 1999
- Xuser \-u Your login name on the server
- Xpass \-p Your password on the server; see below
- Xdir \-d Directory for server to change to
- Xfile \-f File to read (if not Codafile) in the directory given above
- X \-n No action, just report what would be changed
- Xroot \-r Path to find files in; overrides what the Codafile declared
- Xslow \-s Do byte-for-byte comparisons
- X \-t Trace the protocol
- Xverbose \-v How much information to show
- Xyounger \-y Allow newer files to be on the client
- Xowner \-o Retain original ownership
- X.fi
- X.RE
- X.PP
- XIf your password is not listed in the config file, or specified on the
- Xcommand line,
- X.I coda
- Xwill ask you for it.
- XIf you do put your password in the config file, make sure that nobody
- Xelse can read the file!
- X.PP
- XOnce the file has been read, the server will send over a list of
- Xfiles and directories.
- X.I Coda
- Xwill parse this list, and update any files and directories it has to.
- X.PP
- XFor efficiency,
- X.I coda
- Xnormally just checks the sizes of the local and master copy, and will only
- Xupdate the local copy if they are different.
- XIf the modification dates are different,
- X.I coda
- Xwill get a copy of the file and do a byte-for-byte comparison to see if
- Xthe files actually are different.
- XIf the ``\-s'' flag is used,
- X.I coda
- Xwill ignore the time check, and will get every file
- Xand compare it with the local copy.
- X.PP
- XIf you use the ``\-n'' flag,
- X.I coda
- Xwill not do work, but will instead just report what files
- Xand directories are out of date.
- X.PP
- XDuring a port, a client will often have files that have been modified after
- Xthey have been obtained from the server, but before the changes have been
- Xintegrated into the master sources.
- XOn systems where the client's timestamp can be trusted (e.g., not on VMS
- Xbecause there is no equivalent of the
- X.IR utime (2)
- Xcall), the ``\-y'' flag may be used to specify that the client might
- Xhave files that are younger, or more recent, than those on the server.
- XThe default option, ``\-yn'' will cause
- X.I coda
- Xto check if the files are different, and overwrite them, if the timestamps
- Xare different in any way.
- X.PP
- XBy default the person who runs
- X.I coda
- Xwill be the owner of the files.
- XTo make the ownerships match those on the server, use the ``\-oy'' flag.
- XThis is probably more correct in a production environment than when
- Xporting.
- X.PP
- XIf you use the ``\-v'' flag,
- X.I coda
- Xwill give more verbose information about what it is doing.
- XFor example, ``\-v1'' will list all files and directories that have
- Xto be created.
- XIf you use the ``\-v2'' flag,
- X.I coda
- Xwill report when it has to change the ownership or permission on files,
- Xsuch as when a file has the right time and size, but is owned by the
- Xwrong person.
- XSince it is normally not a big problem if the wrong person owns a file,
- Xor if it has the wrong permissions,
- X.I coda
- Xdoes not complain if something cannot be fixed.
- XYou can use the ``\-v3'' flag to see a message whenever the program
- Xcannot set the file mode or ownership.
- XIf you use the ``\-v4'' flag
- X.I coda
- Xwill report on every file as it does the byte-for-byte comparison of slow mode.
- XYou should probably always use either ``\-v1'' or ``\-v3.''
- X.PP
- XTo trace all interactions with the server, use the ``\-t'' flag; this
- Xwill provide output like the following:
- X.RS
- X.nf
- X\fIprompt%\fP coda -d/usr/rsalz -f coda/Codafile -h papaya -u rsalz -x ... -t misc
- X<<<ACK-Hello FIG.BBN.COM; how are you today?
- X>>>USER rsalz ...
- X<<<ACK-Logged in rsalz
- X>>>GOTO /usr/rsalz
- X<<<ACK-Done
- X>>>READ coda/Codafile
- X<<<ACK-Done
- XDoing misc...
- X>>>LIST misc
- X<<<DAT ITEM W=d N=cbin U=-2 G=121 M=511 S=512 T=609796129
- X<<<DAT ITEM W=f N=cbin/dcc U=-2 G=121 M=493 S=150 T=603474106
- X ...
- X<<<ACK-Found 105 files
- XFound 105 files
- Xmkdir cbin
- XUpdate cbin/dcc
- X ...
- X>>>QUIT
- X\fIprompt%\fP
- X.fi
- X.RE
- X(Lines without the angle brackets are the
- X.IR coda 's
- Xnormal output.)
- XThis is detailed information and generally nobody but your local
- X.I coda
- Xmaintainer will care.
- X.PP
- XThe ``\-c'' flag prints out copyright and version information.
- X.SH "CODAFILES"
- XThe coda server reads a file to determine what parts of a distribution
- Xget sent to which hosts.
- XThe file is normally named
- X.IR Codafile .
- XThis section explains how to write codafiles, and does not have to
- Xbe read by everyone.
- X.PP
- XBlank lines are ignored, as is anything after a pound sign.
- XWhitespace is not significant.
- XThere are a few keywords, and they appear in bold in the examples
- Xbelow.
- XTo use a keyword as a filename (e.g., if you have a directory named
- X.IR class ),
- Xput it in quotes.
- XIt is also necessary to quote words if they contain any characters
- Xother than letters, numbers, or the characters period, slash, or underscore.
- X.PP
- XThere are four constructs in a Codafile: parameter definitions,
- Xhost definitions, class definitions, and file definitions or blocks.
- XThey may appear in any order.
- X.PP
- XParameter definitions are a catch-all for miscellaneous parameters.
- XThere are currently three parameters.
- XMost pathnames in a Codafile will be relative paths, the ``root''
- Xis used for any directories or files that do not start with a slash.
- XFor example:
- X.RS
- X\fBdefine\fP \fBroot\fP \fB=\fP /usr/cronus \fB;\fP
- X.RE
- XThis is most useful when the Codafile for a system is not at
- Xthe top of the directory tree, or when it exists in someone's home
- Xdirectory.
- X.PP
- XAt times it is useful to use the same Codafile for several different
- Xsource trees.
- XThe easiest way to do this is to not allow the clients to specify the
- Xdifferent roots.
- XSince this can be a security hole, a Codafile can specify that
- Xthe root directory specified in the file may not be overridden by the
- Xclient.
- XTo do this, use the following line:
- X.RS
- X\fBdefine\fP \fBrooted\fP \fB=\fP yes \fB;\fP
- X.RE
- XThe value can be any word starting with the letter
- X.IR y .
- XThe default value is \fIno\fP
- X.PP
- XThe final parameter controls whether or not binary files are sent.
- XWhen preparing a list of files, the server can read the first few bytes
- Xto see if a file is an ``a.out'' file, and if so, it will not list it.
- XTo suppress this check, add a line like this:
- X.RS
- X\fBdefine\fP \fBbinaries\fP \fB=\fP yes \fB;\fP
- X.RE
- XThe value can be any word starting with the letter
- X.IR y .
- XThe default value is \fIyes\fP
- X.PP
- XHost definitions are used to name the hosts that are allowed to
- Xreceive the distribution, and to identify the system type.
- XBoth the names and types are arbitrary text strings; host names
- Xare converted to all uppercase.
- XA client's hostname must be defined in the Codafile before the server
- Xwill send any files to it.
- X.RS
- X.nf
- X.ta \w'host 'u +\w'pineapple.bbn.com 'u +\w'= 'u
- X\fBhost\fP citron.bbn.com \fB=\fP VMS \fB;\fP
- X\fBhost\fP pineapple.bbn.com \fB=\fP ultrix \fB;\fP
- X\fBhost\fP doe.bbn.com \fB=\fP sun4 \fB;\fP
- X\fBhost\fP papaya.bbn.com \fB=\fP sun3 \fB;\fP
- X.fi
- X.RE
- XIf for some reason the server cannot determine the client's host name,
- Xthen the name
- X.I _ANYHOST
- Xis used.
- X.PP
- XIn order to make the Codafile shorter, hosts are grouped into classes.
- XFor example, it is convenient to be able to say ``give all the Unix
- Xmachines the files in foo.''
- XClasses are defined in two ways, by being named as a system type in a
- Xhost definition, like above, or by appearing in a class definition,
- Xlike this:
- X.RS
- X.nf
- X.DT
- X\fBclass\fP SUN \fB=\fP sun3, sun4 \fB;\fP
- X\fBclass\fP UNIX \fB=\fP SUN, ultrix \fB;\fP
- X.fi
- X.RE
- XNote that classes can be nested and can contain other classes.
- XIn particular, it is possible to make loops that will tie the server
- Xup in knots.
- XUnlike host names, case is significant in class names.
- XBy convention, classes defined as host types are in lowercase, while
- Xthose defined as class types are in uppercase.
- XThe special built-in class
- X.I _ALL
- Xcontains all hosts except
- X.IR _ANYHOST .
- XA Codafile for a public archive might start off like this:
- X.RS
- X.nf
- X.ta \w'define 'u +\w'_ANYHOST 'u
- X\fBdefine\fP \fBroot\fP \fB=\fP /usr/spool/ftp \fB;\fP
- X\fBdefine\fP \fBbinaries\fP \fB=\fP no \fB;\fP
- X\fBhost\fP _ANYHOST \fB=\fP guest \fB;\fP
- X\fBclass\fP WORLD \fB=\fP _ALL, _ANYHOST \fB;\fP
- X.fi
- X.RE
- X.PP
- XThe most important part of a Codafile is the file definitions, or blocks.
- XThese have the following syntax (optional items are shown in square brackets):
- X.RS
- X.nf
- X.DT
- X[ \fBonly_explicitly\fP ] name \fB:\fP class \fB{\fP
- X item
- X [ \fBexcept\fP [\fBdirectory\fP] class pattern, ... ; ]
- X [ \fBexcept\fP [\fBdirectory\fP] class pattern, ... ; ]
- X item
- X ...
- X \fBdirectory\fP item
- X [ \fBexcept\fP [\fBdirectory\fP] class pattern, ... ; ]
- X\fB}\fP
- X.fi
- X.RE
- XThe name is used by client programs to limit the set of files they
- Xwant to receive, while the class is used by the server to determine
- Xif the client has any access to the block at all.
- XIf a client does not name specific blocks, then all blocks in the file are
- Xexamined.
- XIf a block starts with the \fIonly_explicitly\fP keyword, than it must
- Xbe explicitly named by the client, otherwise it is not listed.
- XThis is useful, for example, when the default is to distribute a complete
- Xsystem without test data.
- X.PP
- XWithin the block, each item names either a file or a directory.
- XIf the item does not start with a slash, then the root is prepended.
- XIf the item is a directory, than the server will walk down all the
- Xfiles and directories beneath the named item.
- XTo name just a directory, put the word \fIdirectory\fP before the
- Xitem name.
- XFor example:
- X.RS
- X.nf
- Xheaders \fB:\fP _ALL \fB{\fP
- X include
- X \fBdirectory\fP cetc
- X cetc/hostfile
- X cetc/typefile
- X /etc/motd
- X\fB}\fP
- X.fi
- X.RE
- XThis specifies that all hosts get the directory named
- X.I include
- Xand all files and directories within it.
- XThe next three lines specify that all clients should have the
- X.I cetc
- Xdirectory and the two files
- X.I hostfile
- Xand
- X.I typefile
- Xwithin it.
- XThe actual location of these files on the server depends on the value
- Xof the root parameter.
- XTheir location on the client is relative to the directory from which the
- X.I coda
- Xwas first invoked.
- XThe last line specifies that the motd file
- Xshould exist with the indicated full pathname, regardless of the value
- Xof the root parameter, or where the client is being run from.
- X.PP
- XItems can be given exception lists.
- XException lists are patterns similar to shell wildcards:
- X.RS
- X.nf
- X.ta \w'Character 'u
- XCharacter Meaning
- X? Any single character
- X* Zero or more characters
- X[abc..09] Any single character inside the brackets
- X The sequence ``a-z'' can be used to mean ``abcdefghijklmnopqrstuvwxyz''
- X[^a-z] Any single character not inside the brackets.
- X\ex The character ``x'' has no special meaning (e.g., \e?)
- X.fi
- X.RE
- XException patterns only match against the last part of the pathname.
- XThat is,
- X.I mgr.c
- Xand not
- X.IR /usr/cronus/src/lib/asynclib/mgr.a .
- XTo match against the whole pathname, precede the pattern with an uparrow.
- XThis can be necessary when you want to exclude a particular file that
- Xhas the same part of name as a directory further up in the source tree.
- X.PP
- XFor example, with the following hierarchy:
- X.RS
- X.nf
- Xclib/commandfile
- Xclib/cronus.a
- Xclib/diamond/fonts/helvetica10.font
- Xclib/diamond/fonts/tv8b.font
- Xclib/diamond/lib.a
- Xclib/diamond/config
- Xclib/editkeysfile
- Xclib/lint/llib-lasync
- Xclib/lint/llib-lasync.ln
- Xclib/lint/llib-lulib
- Xclib/lint/llib-lulib.ln
- Xclib/malloctool.a
- X.fi
- X.RE
- XAnd the following block definition:
- X.RS
- X.nf
- Xlibrary \fB:\fP _ALL {
- X clib
- X \fBexcept\fP _ALL "*.a", "*.ln" \fB;\fP
- X \fBexcept\fP \fBdirectory\fP VMS diamond, lint \fB;\fP
- X}
- X.fi
- X.RE
- XThen, no clients will get the compiled libraries or
- X.IR lint (1)
- Xlibraries,
- Xand VMS clients will not get any files in the lint or diamond directories.
- XAll clients will get the (presumably text) files named
- X.IR commandfile ,
- Xand
- X.IR editkeysfile .
- X.PP
- XWith a good set of classes it is quite easy to tersely specify distributions.
- XThe following example suffices to distribute the major part of the
- XCronus source tree:
- X.RS
- X.nf
- Xsources \fB:\fP _ALL \fB{\fP
- X src
- X \fBexcept\fP VMS Makefile, "*.sh", "*.s", "llib-l*" \fB;\fP
- X \fBexcept\fP UNIX descrip.mms, "*.opt", "*.com", "*.mar" \fB;\fP
- X \fBexcept\fP _ALL "*.[oa]", "*.ln" \fB;\fP
- X \fBexcept\fP _ALL a.out, core, foo, tags \fB;\fP
- X\fB}\fP
- X.fi
- X.RE
- X.SH AUTHOR
- XThis program was written by Rich $alz <rsalz@bbn.com>.
- XIt has the following copyright:
- X.RS
- X.nf
- XCopyright 1989 BBN Systems and Technologies Corporation.
- XAll Rights Reserved.
- XThis is free software, and may be distributed under the terms of the
- XGNU Public License; see the file COPYING for more details.
- X
- X$Header: coda.1,v 2.0 90/03/23 15:01:50 rsalz Exp $
- X.fi
- X.RE
- X.SH "SEE ALSO"
- Xcodaserver(8).
- END_OF_FILE
- if test 14762 -ne `wc -c <'coda.1'`; then
- echo shar: \"'coda.1'\" unpacked with wrong size!
- fi
- # end of 'coda.1'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- exit 0 # Just in case...
-